/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/
package ichain

import (
	"time"

	"git.cloud.inspur.com/ichain/ichain-sdk-go/pkg/common/errors/retry"
	x509GM "github.com/tjfoc/gmsm/x509"
)

// NetworkConfig 整个区块链网络的配置对象
type NetworkConfig struct {
	// Chains 所有的链节点配置
	Chains map[string]ChainEndpointConfig
	// Organizations 所有的组织配置
	Organizations map[string]OrganizationConfig
	// Consensers 所有共识节点的配置
	Consensers map[string]ConsenserConfig
	// Inodes inode节点配置
	Inodes map[string]InodeConfig
}

// ChainEndpointConfig 链节点以及inode节点配置
type ChainEndpointConfig struct {
	// Consensers 共识节点列表
	Consensers []string
	// Inodes inode节点 key：inode名字
	Inodes map[string]InodeChainConfig
	//Policies 请求链的配置
	Policies ChainPolicies
}

// ChainPolicies 链的请求策略配置
type ChainPolicies struct {
	QueryChainConfig QueryChainConfigPolicy // 请求链配置策略
	Discovery        DiscoveryPolicy        // 服务发现策略
	Selection        SelectionPolicy        // 背书节点选择策略
	EventService     EventServicePolicy     // 事件订阅节点策略
}

// QueryChainConfigPolicy 请求链配置策略
type QueryChainConfigPolicy struct {
	MinResponses int        // 最小回复个数
	MaxTargets   int        // 请求节点的最大个数
	RetryOpts    retry.Opts // 重试配置
}

// DiscoveryPolicy 服务发现策略
type DiscoveryPolicy struct {
	MinResponses int        // 最小回复个数
	MaxTargets   int        // 最大请求个数
	RetryOpts    retry.Opts // 重试配置
}

// SelectionSortingStrategy 选择背书节点的排序策略
type SelectionSortingStrategy string

const (
	// BlockHeightPriority 默认该策略，按照区块高度排序，选取两部分， 一部分为大于最大高度与阈值高度差，
	//另一部分为小于，大于的部分继续采用轮盘赌方式排序，小于的部分按区块高度从小到大排序；Balanced轮盘赌方式排序背书节点
	BlockHeightPriority SelectionSortingStrategy = "BlockHeightPriority"

	// Balanced 负责均衡去选择背书节点
	Balanced SelectionSortingStrategy = "Balanced"
)

type BalancerType string

const (
	// RoundRobin  默认策略，轮盘赌的方式
	RoundRobin BalancerType = "RoundRobin"

	// Random 随机负载均衡
	Random BalancerType = "Random"
)

// SelectionPolicy 背书选择策略
type SelectionPolicy struct {
	SortingStrategy SelectionSortingStrategy
	// BalancerType 负载均衡类型
	Balancer BalancerType
	// BlockHeightLagThreshold 区块高度的比较阈值
	BlockHeightLagThreshold int
}

// InodeChainConfig inode节点功能配置
type InodeChainConfig struct {
	EndorsingInode bool // 能否背书
	ContractQuery  bool // 能否请求合约
	LedgerQuery    bool // 能否请求账本
	EventSource    bool // 能否事件订阅
}

// ChainInode 链节点
type ChainInode struct {
	InodeChainConfig // inode功能
	NetworkInode     // inode网络配置
}

// NetworkInode 节点配置+iam+属性
type NetworkInode struct {
	InodeConfig
	IAMID      string
	Properties map[Property]interface{}
}

// OrganizationConfig 组织配置
type OrganizationConfig struct {
	IAMID                  string
	CryptoPath             string
	Users                  map[string]CertKeyPair
	Inodes                 []string
	CertificateAuthorities []string
}

// ConsenserConfig 共识节点配置
type ConsenserConfig struct {
	URL         string
	GRPCOptions map[string]interface{}
	TLSCACert   *x509GM.Certificate
}

// InodeConfig inode配置包括url grpc的选择项 以及tls证书
type InodeConfig struct {
	URL         string
	GRPCOptions map[string]interface{}
	TLSCACert   *x509GM.Certificate
}

// CertKeyPair 证书密钥对
type CertKeyPair struct {
	Cert []byte
	Key  []byte
}

type ResolverStrategy string

const (
	// BalancedStrategy 随机或者轮盘赌的方式选择一个
	BalancedStrategy ResolverStrategy = "Balanced"

	// MinBlockHeightStrategy 首先遍历所有inode节点的区块高度，与设置最小区块高度-区块滞后阈值做对比，在大于的inode节点里再随机选择一个
	MinBlockHeightStrategy ResolverStrategy = "MinBlockHeight"

	// PreferOrgStrategy 先根据MinBlockHeight策略过滤inode节点，然后优先选择同一组织的inode节点
	PreferOrgStrategy ResolverStrategy = "PreferOrg"
)

type MinBlockHeightResolverMode string

const (
	ResolveByThreshold MinBlockHeightResolverMode = "ResolveByThreshold"

	ResolveLatest MinBlockHeightResolverMode = "ResolveLatest"
)

// EnabledDisabled 是否某个特性被开启
type EnabledDisabled string

const (
	Enabled EnabledDisabled = "Enabled"

	Disabled EnabledDisabled = "Disabled"
)

// EventServicePolicy 事件服务策略
type EventServicePolicy struct {
	// ResolverStrategy Default: MinBlockHeightInodeResolver 选择event服务的策略
	ResolverStrategy ResolverStrategy

	// Balancer 负载均衡
	Balancer BalancerType

	MinBlockHeightResolverMode MinBlockHeightResolverMode
	BlockHeightLagThreshold    int

	// InodeMonitor 是否开启event检测
	InodeMonitor EnabledDisabled

	// ReconnectBlockHeightLagThreshold 区块高度低于该阈值就断开event服务
	ReconnectBlockHeightLagThreshold int

	// InodeMonitorPeriod inode检测周期
	InodeMonitorPeriod time.Duration
}
